﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using blackhouse.WebNemo.Data;
using System.IO;

namespace blackhouse.WebNemo.Business.Groups {
    public class DaGroupRecord : IGroupRecord {

        #region Fields

        private ImpGroupRecord instance;
        private IDataAccess data;
        private IGroup group;

        #endregion

        #region Properties

        public string Identyficator { get { return this.instance.Identyficator; } private set { this.instance.Identyficator = value; } }

        public int RecordId { get { return this.instance.RecordId; } private set { this.instance.RecordId = value; } }

        public int BelongsToGroupId { get { return this.instance.BelongsToGroupId; } private set { this.instance.BelongsToGroupId = value; } }

        public DateTime CreatedTime { get { return this.instance.CreatedTime; } private set { this.instance.CreatedTime = value; } }

        public int CreatedBy { get { return this.instance.CreatedBy; } private set { this.instance.CreatedBy = value; } }

        public DateTime LastModifiedTime { get { return this.instance.LastModifiedTime; } private set { this.instance.LastModifiedTime = value; } }

        public int LastModifiedBy { get { return this.instance.LastModifiedBy; } private set { this.instance.LastModifiedBy = value; } }

        public object this[string column] {
            get { return this.instance[column]; }
            private set { this.instance[column] = value; }
        }

        #endregion

        #region Constructors

        public DaGroupRecord(int groupId, IDataAccess data) {
            this.data = data;
            this.instance = new ImpGroupRecord();
            this.BelongsToGroupId = groupId;
        }

        public DaGroupRecord(int groupId, IDataAccess data, GroupRecordData recordData) {
            this.data = data;
            this.instance = this.ConvertToInstance(recordData);
            this.BelongsToGroupId = groupId;
        }

        #endregion

        #region Methods

        private ImpGroupRecord ConvertToInstance(GroupRecordData data) {
            ImpGroupRecord instance = new ImpGroupRecord();
            instance.CreatedBy = data.CUser;
            instance.CreatedTime = data.CTime;
            instance.Identyficator = data.Identyficator;
            instance.LastModifiedBy = data.MUser;
            instance.LastModifiedTime = data.MTime;
            instance.RecordId = data.Idx;

            foreach (KeyValuePair<string, object> item in data) {
                instance[item.Key] = item.Value;
            }
            return instance;
        }

        private GroupRecordData ConvertToData() {
            GroupRecordData data = new GroupRecordData();
            data.CUser = this.CreatedBy;
            data.CTime = this.CreatedTime;
            data.Identyficator = this.Identyficator;
            data.MUser = this.LastModifiedBy;
            data.MTime = this.LastModifiedTime;
            data.Idx = this.RecordId;

            foreach (GroupColumn column in this.GetGroup().Columns.Where(cn => !string.IsNullOrEmpty(cn.SelectColumnName) && this.IsUpdated(cn.ColumnName))) {
                GroupRecordDataValue value = new GroupRecordDataValue(column.DataType.ToDbType(), this[column.ColumnName]);
                data.Add(column.SelectColumnName, value);
            }
            return data;
        }

        public IGroup GetGroup() {
            if (this.group == null || this.group.Id != this.BelongsToGroupId)
                this.group = Factory.Instance().GetGroup(this.BelongsToGroupId);
            return this.group;
        }

        public object GetValue(string column) {
            return this.instance.GetValue(column);
        }

        private Dictionary<string, SaveFile> filesToSave = new Dictionary<string, SaveFile>();

        public object SetValue(string column, object value) {
            if (value is SaveFile) { // to znaczy, że mamy plik
                filesToSave.Add(column, value as SaveFile);
                return null;
            }
            else
                return this.instance.SetValue(column, value);
        }

        public bool IsUpdated(string column) {
            return this.instance.IsUpdated(column);
        }

        public void ChangeIdentyficator(string ident) {
            this.instance.ChangeIdentyficator(ident);
            this.data.ChangeIdentyficator(this.BelongsToGroupId, this.RecordId, ident, Factory.Instance().GetCurrentUser().UserId);
        }

        public void Remove() {
            this.data.RemoveRecord(this.BelongsToGroupId, this.RecordId, Factory.Instance().GetCurrentUser().UserId);
            this.instance = new ImpGroupRecord();
        }

        public void Save() {
            this.Save(Factory.Instance().GetCurrentUser().UserId);
        }

        public void Save(int userId) {
            if (this.RecordId > 0) {
                if (this.GetGroup().Type == GroupType.ExtendedTable) {
                    if (this.GetValue(this.GetGroup().SelectTable.ToLower() + "_idx") == DBNull.Value) {
                        GroupRecordData data = this.ConvertToData();
                        data.Add("idx", new GroupRecordDataValue(System.Data.DbType.Int32, this.RecordId));
                        this.data.AddGroupRecord(data, this.BelongsToGroupId, userId);
                    }
                    else
                        this.data.SaveGroupRecord(this.ConvertToData(), this.BelongsToGroupId, this.RecordId, userId);
                }
                else {
                    if (this.RecordId == 0 || this.instance.RecordShouldBeUpdated())
                        this.data.SaveGroupRecord(this.ConvertToData(), this.BelongsToGroupId, this.RecordId, userId);
                }
            }
            else {
                this.RecordId = this.data.AddGroupRecord(this.ConvertToData(), this.BelongsToGroupId, userId);
                if (!string.IsNullOrEmpty(this.Identyficator))
                    this.ChangeIdentyficator(this.Identyficator);
            }
            foreach (KeyValuePair<string, SaveFile> entry in this.filesToSave) {
                this.SaveFile(entry.Key, entry.Value);
            }
            this.filesToSave.Clear();
        }

        private void SaveFile(string column, SaveFile file) {
            RecordFile rFile = new RecordFile(this, column);
            rFile.SaveFile(file.FileName, file.FileStream);
            //this.data.SaveGroupRecordFile(this.BelongsToGroupId, this.RecordId, column, file.Name, file.Stream, file.Stream.Length, Factory.Instance().GetCurrentUser().UserId);
        }

        #endregion

    }
}
